#include "SnzApplicationManager.h"               


/// Constructor initializes pointers to 0
SnzApplicationManager::SnzApplicationManager() 
{
    mRoot = 0;
    mFrameListener = 0;
    mCamera = 0;
    mSceneMgr = 0;
	mWindow = 0;

    //mInputManager=0;
    //mInputHandler=0;
    //mRaySceneQuery = 0;
    //mGUIRenderer = 0;
    //mGUISystem = 0;
}
template<> SnzApplicationManager* Singleton<SnzApplicationManager>::ms_Singleton = 0;

/// Destructor shuts down Ogre in the proper order.
SnzApplicationManager::~SnzApplicationManager() 
{
    // destroyScene() is called before shutting down this object.
    // Delete classes I created
    
	// REALMENTE NAO PERCEBO PORQUE E QUE ESTA MERDA NAO FUNCIONA
	/*if (mFrameListener)
		delete mFrameListener;
    if (mRoot)
        delete mRoot;*/
	// ~ REALMENTE NAO PERCEBO

    //delete mInputManager;
    //delete mInputHandler;
  

}  // ~SnzApplicationManager


/********************************************************************************
 * INITIALIZERS *****************************************************************/

/// Framework is started with a call to this function 
void SnzApplicationManager::start() 
{
	if(!init())
		return;

	mRoot->startRendering();

	destroyScene();

}

/// From start() we go through the process of creating all necessary objects.
bool SnzApplicationManager::init() 
{

	#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
		//mResourcePath = "";
	#else
		mResourcePath = "";
	#endif

    mRoot = new Root(mResourcePath + "plugins.cfg", mResourcePath + "ogre.cfg");

    setupResources();     
		//Pops out Configuration menu
		if(!configure())
			return false;

	chooseSceneManager();
    createCamera();
    createViewports();

    // set default mipmap level (some APIs ignore this)
    TextureManager::getSingleton().setDefaultNumMipmaps(5);

    loadResources();

	createScene();

	createFrameListener();

    //_initInput();

	return true;

}

/// Setup Resources
void SnzApplicationManager::setupResources()
{
	ResourceGroupManager *rgMgr = ResourceGroupManager::getSingletonPtr();	
	ConfigFile file;
	file.load("resources.cfg");
	ConfigFile::SectionIterator seci = file.getSectionIterator();
	String secName, typeName, archiveName;
	while(seci.hasMoreElements())
	{
		secName = seci.peekNextKey();
		ConfigFile::SettingsMultiMap *settings = seci.getNext();
		ConfigFile::SettingsMultiMap::iterator i;
		for(i = settings->begin(); i != settings->end(); i++)
		{
			typeName = i->first;
			archiveName = i->second;
			rgMgr->addResourceLocation(archiveName,typeName,secName);
		}
	}
}




/// Setup the initial scene.
void SnzApplicationManager::createScene() 
{
	//ESTE CODIGO VAI SAIR DAQUI ------------------------

	Entity *ent = mSceneMgr->createEntity("Ninja", "OgreHead.mesh");
    SceneNode *node = mSceneMgr->getRootSceneNode()->createChildSceneNode("NinjaNode");
    node->attachObject(ent);

	//~ESTE CODIGO VAI SAIR DAQUI ------------------------

}


/// Create and register Listener with Ogre.
void SnzApplicationManager::createFrameListener() 
{
	//mFrameListener = new SnzFrameListener();
	//mRoot->addFrameListener(mFrameListener);
	mFrameListener= new ExampleFrameListener(mWindow, mCamera);
	mFrameListener->showDebugOverlay(true);
    mRoot->addFrameListener(mFrameListener);
}

/// Perform resource group loading
void SnzApplicationManager::loadResources() 
{
    // Must at least do this
    ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}

/// Configures the application - returns false if the user chooses to abandon configuration.
bool SnzApplicationManager::configure()
{
    // Show the configuration dialog and initialise the system
    // You can skip this and use root.restoreConfig() to load configuration
    // settings if you were sure there are valid ones saved in ogre.cfg
    if(mRoot->showConfigDialog())
    {
        // If returned true, user clicked OK so initialise
        // Here we choose to let the system create a default rendering window by passing 'true'
        mWindow = mRoot->initialise(true);
        return true;
    }
    else
        return false;
}
/// Create the SceneManager
void SnzApplicationManager::chooseSceneManager()
{
    mSceneMgr = mRoot->createSceneManager(ST_GENERIC, "SnzSceneManager");
}


/// Create the camera
void SnzApplicationManager::createCamera()
{
    mCamera = mSceneMgr->createCamera("PlayerCam");

    // Position it at 500 in Z direction
    mCamera->setPosition(Vector3(0,0,500));
    // Look back along -Z
    mCamera->lookAt(Vector3(0,0,-300));
    mCamera->setNearClipDistance(5);

}

/// Create Viewports
void SnzApplicationManager::createViewports()
{
    // Create one viewport, entire window
    Viewport* vp = mWindow->addViewport(mCamera);
    vp->setBackgroundColour(ColourValue(0,0,0));

    // Alter the camera aspect ratio to match the viewport
    mCamera->setAspectRatio(
        Real(vp->getActualWidth()) / Real(vp->getActualHeight()));
}


/********************************************************************************
 * DESTROYERS *******************************************************************/

/// Perform any functions necessary for destroying the scene.
void SnzApplicationManager::destroyScene() 
{
    delete mCamera;

    // Delete all objects
    /*ObjectMapIt it;
    for (it=mObjectList.begin(); it != mObjectList.end(); ++it) 
    {
        LOG(DEBUG,"ApplicationManager::_destroyScene: Deleting object: %s\n", 
                                            (it->first).c_str(), it->second);
        delete it->second;
    }
    mObjectList.clear();*/
    
    mSceneMgr->clearScene();

    //mSceneMgr->destroyQuery(mRaySceneQuery);

    /*LOG(DEBUG, "ApplicationManager: Deleting CEGUI\n");
    delete mGUISystem;
    delete mGUIRenderer;*/
}



/********************************************************************************
 * GETTERS **********************************************************************/
ExampleFrameListener* SnzApplicationManager::getFrameListener()
{
    return mFrameListener;
}

Camera* SnzApplicationManager::getCamera()
{
    return mCamera;
}

SceneManager* SnzApplicationManager::getSceneManager()
{
    return mSceneMgr;
}

RenderWindow* SnzApplicationManager::getRenderWindow()
{
    return mWindow;
}


/// Returns a reference to the instance of SnzApplicationManager
SnzApplicationManager& SnzApplicationManager::getSingleton()
{
    assert(ms_Singleton);               // Verify pointer is valid or die
    return *ms_Singleton;
}


/// Returns a pointer to the instance of SnzApplicationManager
SnzApplicationManager* SnzApplicationManager::getSingletonPtr()
{
    return ms_Singleton;
}
















































/// Create any additional resource listeners (e.g. for loading screens)
/*void ApplicationManager::_createResourceListener() 
{ 
}*/

/// Listener calls this each frame.  This manager calls every other manager as
/// appropriate.
/* bool ApplicationManager::frameStarted(const FrameEvent &evt)
{
    // Process input events
    mInputManager->frameStarted(evt);

    // Animate each object in the world
    ObjectMapIt it;
    for (it=mObjectList.begin(); it != mObjectList.end(); ++it) 
        it->second->frameStarted(evt);

    // Process camera
    mCamera->frameStarted(evt);
    return true;
} */

/// Listener calls this each frame.  This manager calls every other manager as
/// appropriate.
/*bool ApplicationManager::frameEnded(const FrameEvent &evt) 
{
    return true;
}




/// Returns the raySceneQuery associated with the current scene manager.
/*RaySceneQuery* ApplicationManager::getRaySceneQuery()
{
    return mRaySceneQuery;
} */

/*InputManager* ApplicationManager::getInputManager()
{
    return mInputManager;
}

InputHandler* ApplicationManager::getInputHandler()
{
    return mInputHandler;
}

ObjectMap& ApplicationManager::getObjectList() 
{
    return mObjectList;
}*/